﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace MapApp
{
    class MyMap
    {
        // объекты карты
        private List<Point> listPoints;
        // фоновая картинка
        private Picture pic;
        // количество объектов
        private int length;

        #region конструкторы

        public MyMap()
        {
            listPoints = new List<Point>();
            length = 0;
        }

        public MyMap(Picture p)
        {
            listPoints = new List<Point>();
            pic = new Picture(p);
            length = 0;
        }

        public MyMap(Picture p, Point[] points)
        {
            listPoints = new List<Point>();
            pic = new Picture(p);
            foreach (Point point in points)
            {
                listPoints.Add(point);
            }
            length = listPoints.Count;
        }

        public MyMap(MyMap m)
        {
            listPoints = new List<Point>(m.listPoints);
            //pic = new Picture(m.pic);
            length = m.length;
        }

        #endregion

        // добавление объекта на карту
        public void AddPoint(Point point)
        {
            if ((point.GetLocation()[0] < 0) | (point.GetLocation()[1] < 0) | (point.GetLocation()[0] > pic.GetSize()[0]) | (point.GetLocation()[1] > pic.GetSize()[1]))
            {
                throw new Exception("Неправильные координаты");
            }

            Point p1 = null;
            foreach (Point p in listPoints)
            {
                if ((point.GetLocation()[0] == p.GetLocation()[0]) && (point.GetLocation()[1] == p.GetLocation()[1]))
                {
                    p1 = p;
                }
            }
            if (p1 != null)
            {
                listPoints.Remove(p1);
            }

            listPoints.Add(new Point(point));
            length++;

        }

        public int GetLength()
        {
            return length;
        }

        public Image GetImage()
        {
            return pic.GetImage();
        }

        public void SetImage(Bitmap pic, int[,] mtrx, int offset, Func<Bitmap, int[,], int, Bitmap> img)
        {
            this.pic.SetImage(pic, mtrx, offset, img);
        }

        #region перегрузки операторов

        //получает карту с фоновым изображением из 1 операнда и объектами, которые есть хотя бы на одной из карт
        public static MyMap operator +(MyMap m1, MyMap m2)
        {
            MyMap result = new MyMap(m1);
            foreach (Point p in m2.listPoints)
            {
                result.AddPoint(p);
            }
            return result;
        }

        //получает карту с фоновым изображением из 1 операнда и объектами с первой карты, кроме тех, что есть и во второй
        public static MyMap operator -(MyMap m1, MyMap m2)
        {
            MyMap result = new MyMap(m1);
            foreach (Point p1 in m1.listPoints)
            {
                foreach (Point p2 in m2.listPoints)
                {
                    if ((p1.GetLocation()[0] == p2.GetLocation()[0]) && (p1.GetLocation()[1] == p2.GetLocation()[1]))
                    {
                        result.listPoints.Remove(p1);

                    }
                }
            }
            return result;
        }

        //получает карту с фоновым изображением из 1 операнда и с одинаковыми объектами с двух карт
        public static MyMap operator &(MyMap m1, MyMap m2)
        {
            MyMap result = new MyMap(m1.pic);
            foreach (Point p1 in m1.listPoints)
            {
                foreach (Point p2 in m2.listPoints)
                {
                    if ((p1.GetLocation()[0] == p2.GetLocation()[0]) && (p1.GetLocation()[1] == p2.GetLocation()[1]))
                    {
                        result.AddPoint(p1);

                    }
                }
            }
            return result;
        }

        //аналогично оператору сложения
        public static MyMap operator |(MyMap m1, MyMap m2)
        {
            return m1 + m2;
        }

        #endregion;

        //индексатор
        public Point this[int i]
        {
            set
            {
                if ((i < 0) | (i >= length)) throw new Exception("incorrect index");
                listPoints[i] = value;
            }

            get
            {
                if ((i < 0) | (i >= length)) throw new Exception("incorrect index");
                return listPoints[i];
            }
        }

        public override string ToString()
        {
            return "<< " + String.Join(" ", listPoints);
        }

        //отрисовка карты в объекте PictureBox
        public void Draw(PictureBox pb)
        {
            Graphics graph = pb.CreateGraphics();
            pb.BackgroundImage = GetImage();
            Font fnt = new Font("Verdana", 9.0f);
            Pen pn = new Pen(Color.Red, 3);
            Brush brsh = new SolidBrush(Color.Black);
            foreach (Point p in listPoints)
            {
                graph.DrawEllipse(pn, p.GetLocation()[0], p.GetLocation()[1], 10, 10);
                graph.DrawString(p.GetName(), fnt, brsh, (float)p.GetLocation()[0] + 12, (float)p.GetLocation()[1]);
            }
        }
    }


}
